﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Validity.Contexts;
using Validity.Rules;

namespace Validity.Test.Contexts
{
  [TestClass]
  public class MessageValidationContextTest
  {
    private readonly StubValidationContext<IComparable> _context = new StubValidationContext<IComparable>();
    
    [TestMethod]
    public void TestDefaultCtor()
    {
      Assert.IsNotNull( new MessageValidationContext<ObjectStub, IComparable>());
    }

    [TestMethod]
    public void TestReplacingMessageWithUsingStaticString()
    {
      Assert.IsNotNull(CreateMessageValidationContext().ReplacingMessageWith("New Message"));
      VerifyDecorateedRule(new ObjectStub(), "Some Value", "New Message");
    }

    [TestMethod]
    public void TestReplacingMessageWithUsingDynamicString()
    {
      Assert.IsNotNull(CreateMessageValidationContext().ReplacingMessageWith(() => "New Message"));
      VerifyDecorateedRule(new ObjectStub(), "Some Value", "New Message");
    }

    [TestMethod]
    public void TestReplacingMessageWithUsingDynamicStringBasedOnValue()
    {
      var expectedValue = String.Empty;
      Assert.IsNotNull(CreateMessageValidationContext().ReplacingMessageWith((IComparable val) =>
      {
        Assert.AreEqual(expectedValue, val);
        return "New Message";
      }));
      VerifyDecorateedRule(new ObjectStub(), expectedValue, "New Message");
    }

    [TestMethod]
    public void TestReplacingMessageWithUsingDynamicStringBasedOnObject()
    {
      var expectedObject = new ObjectStub();
      Assert.IsNotNull(CreateMessageValidationContext().ReplacingMessageWith((ObjectStub obj) =>
      {
        Assert.AreEqual(expectedObject, obj);
        return "New Message";
      }));
      VerifyDecorateedRule(expectedObject, "Some Value", "New Message");
    }

    [TestMethod]
    public void TestReplacingMessageWithUsingDynamicStringBasedOnObjectAndValue()
    {
      var expectedObject = new ObjectStub();
      var expectedValue = String.Empty;

      Assert.IsNotNull(CreateMessageValidationContext().ReplacingMessageWith((obj, val) =>
      {
        Assert.AreEqual(expectedObject, obj);
        Assert.AreEqual(expectedValue, val);
        return "New Message";
      }));

      VerifyDecorateedRule(expectedObject, expectedValue, "New Message");
    }

    private MessageValidationContext<ObjectStub, IComparable> CreateMessageValidationContext()
    {
      var context = new MessageValidationContext<ObjectStub, IComparable>(_context);
      var rule = new Rule<ObjectStub, IComparable>((obj, val) => true, (obj, val) => "Original Message");

      _context.Rule.Add(rule);

      return context;
    }

    private void VerifyDecorateedRule(ObjectStub obj, IComparable value, String expectedMessage)
    {
      IRule<ObjectStub, IComparable> rule = _context.Rule[0];

      Assert.AreEqual(expectedMessage, rule.GetRuleViolation(obj, value));
    }

  }
}
